home *** CD-ROM | disk | FTP | other *** search
- /* dirutil.c - MS-DOS directory reading routines
- *
- * Bdale Garbee, N3EUA, Dave Trulli, NN2Z, and Phil Karn, KA9Q
- * Directory sorting by Mike Chepponis, K3MC
- * New version using regs.h by Russell Nelson.
- */
-
- #include <stdio.h>
- #include "global.h"
- #include "regs.h"
-
- #define ST_RDONLY 0x01 /* Read only attribute */
- #define ST_HIDDEN 0x02 /* Hidden file */
- #define ST_SYSTEM 0x04 /* System file */
- #define ST_LABEL 0x08 /* Volume label */
- #define ST_DIRECT 0x10 /* Directory */
- #define ST_ARCH 0x20 /* Archive */
-
- FILE *tmpfile();
- char *getcwd();
-
- #ifndef FALSE
- #define FALSE (0)
- #endif
-
- #ifndef TRUE
- #define TRUE !(FALSE)
- #endif
-
- #define REGFILE (ST_HIDDEN|ST_SYSTEM|ST_DIRECT)
- #define SET_DTA 0x1a
- #define GET_FREE 0x36
- #define FIND_FIRST 0x4e
- #define FIND_NEXT 0x4f
-
- struct dirent {
- char rsvd[21];
- char attr;
- short ftime;
- short fdate;
- long fsize;
- char fname[13];
- };
- #define NULLENT (struct dirent *)0
-
- #define insert_ptr(list,new) (new->next = list,list = new)
-
- struct dirsort {
- struct dirsort *next;
- struct dirent de;
- };
- #define NULLSORT (struct dirsort *)0
-
- /* Create a directory listing in a temp file and return the resulting file
- * descriptor. If full == 1, give a full listing; else return just a list
- * of names.
- */
- FILE *
- dir(path,full)
- char *path;
- int full;
- {
- FILE *fp;
-
- fp = tmpfile();
- getdir(path,full,fp);
- rewind(fp);
- return fp;
- }
-
- /* find the first or next file and lowercase it. */
- int
- nextname(command, name, sbuf)
- int command;
- char *name;
- struct dirent *sbuf;
- {
- struct regs regs;
- register char *cp;
- int found;
-
- _AH = SET_DTA; /* Set disk transfer address */
- _DS = FP_SEG(sbuf);
- _DX = FP_OFF(sbuf);
- sysint(0x21,®s,®s);
-
- _AH = command; /* Find matching file */
- _CX = REGFILE;
- _DS = FP_SEG(name);
- _DX = FP_OFF(name);
-
- found = (sysint(0x21,®s,®s) & FLAG_CARRY) == 0;
-
- if(found){
- /* strlwr(sbuf->fname); */
- cp = sbuf->fname;
- while ((*cp = tolower(*cp)) != '\0')
- cp++;
- }
-
- return found;
- }
-
- /* wildcard filename lookup */
- filedir(name,times,ret_str)
- char *name;
- int times;
- char *ret_str;
- {
- static struct dirent sbuf;
-
- if(!nextname(times == 0 ? FIND_FIRST:FIND_NEXT, name, &sbuf))
- sbuf.fname[0] = '\0';
-
- /* Copy result to output */
- strcpy(ret_str, sbuf.fname);
- }
- /* do a directory list to the stream
- * full = 0 -> short form, 1 is long
- */
- getdir(path,full,file)
- char *path;
- int full;
- FILE *file;
- {
- struct dirent sbuf;
- int command = FIND_FIRST;
- int n = 0;
-
- struct dirsort *head, *here, *new;
- void dir_sort(), free_clist();
- void format_fname_full(), print_free_space();
- char *wildcardize();
-
- path = wildcardize(path);
-
- head = NULLSORT; /* No head of chain yet... */
- for(;;){
- if (!nextname(command, path, &sbuf))
- break;
- command = FIND_NEXT; /* Got first one already... */
- if (sbuf.fname[0] == '.') /* drop "." and ".." */
- continue;
-
- new = (struct dirsort *) malloc(sizeof(struct dirsort));
- if(new == NULLSORT){
- /* Clean up and call other routine */
- free_clist(head);
- return getdir_nosort(path,full,file);
- }
- new->de = sbuf; /* Copy contents of directory entry struct */
-
- /* insert it into the list */
- if (!head || fncmp(new->de.fname, head->de.fname) < 0) {
- insert_ptr(head, new);
- } else {
- register struct dirsort *this;
- for (this = head;
- this->next != NULLSORT;
- this = this->next)
- if (fncmp(new->de.fname, this->next->de.fname) < 0)
- break;
- insert_ptr(this->next, new);
- }
- } /* infinite FOR loop */
-
- for (here = head; here; here = here->next)
- format_fname_full(file,&here->de,full,++n);
-
- /* Give back all the memory we temporarily needed... */
- free_clist(head);
-
- if(full) print_free_space(file, n);
-
- return 0;
- }
- int
- fncmp(a,b)
- register char *a, *b;
- {
- int i;
-
- for(;;){
- if (*a == '.') return -1;
- if (*b == '.') return 1;
- if ((i = *a - *b++) != 0) return i;
- if (!*a++) return -1;
- }
- }
- /* Change working directory */
- docd(argc,argv)
- int argc;
- char *argv[];
- {
- char dirname[128];
-
- if(argc > 1){
- if(chdir(argv[1]) == -1){
- printf("Can't change directory\n");
- return 1;
- }
- }
- if(getcwd(dirname,128) != NULLCHAR){
- printf("\\%s\n",dirname);
- }
- return 0;
- }
- /* List directory to console */
- dodir(argc,argv)
- int argc;
- char *argv[];
- {
- char *path;
-
- if(argc >= 2){
- path = argv[1];
- } else {
- path = "*.*";
- }
- getdir(path,1,stdout);
- return 0;
- }
-
-
- /*
- * Return a string with commas every 3 positions.
- * If malloc() fails, return original string unmodified.
- * else the original string is replace with the string with commas.
- *
- * The caller must be sure that there is enough room for the resultant
- * string.
- *
- *
- * k3mc 4 Dec 87
- */
- void
- commas(dest)
- char *dest;
- {
- char *src, *core; /* Place holder for malloc */
- unsigned cc; /* The comma counter */
- unsigned len;
-
- len = strlen(dest);
- /* Make a copy, so we can muck around */
- if( (core = src = strdup(dest)) == NULLCHAR)
- return;
-
- cc = (len-1)%3 + 1; /* Tells us when to insert a comma */
-
- while(*src != '\0'){
- *dest++ = *src++;
- if( ((--cc) == 0) && *src ){
- *dest++ = ','; cc = 3;
- }
- }
- free(core);
- *dest = '\0';
- }
- /* fix up the filename so that it contains the proper wildcard set */
- char *
- wildcardize(path)
- char *path;
- {
- struct dirent sbuf;
- static char ourpath[64];
-
- /* Root directory is a special case */
- if(path == NULLCHAR ||
- *path == '\0' ||
- strcmp(path,"\\") == 0 ||
- strcmp(path,"/") == 0)
- path = "\\*.*";
-
- /* if they gave the name of a subdirectory, append \*.* to it */
- if (nextname(FIND_FIRST, path, &sbuf) &&
- (sbuf.attr & ST_DIRECT) &&
- !nextname(FIND_NEXT, path, &sbuf)) {
-
- /* if there isn't enough room, give up -- it's invalid anyway */
- if (strlen(path) + 4 > 63) return path;
- strcpy(ourpath, path);
- strcat(ourpath, "\\*.*");
- return ourpath;
- }
- return path;
- }
-
- void
- format_fname_full(file, sbuf, full, n)
- FILE *file;
- struct dirent *sbuf;
- int full, n;
- {
- char line_buf[50]; /* for long dirlist */
- char cbuf[20]; /* for making line_buf */
-
- strcpy(cbuf,sbuf->fname);
- if(sbuf->attr & ST_DIRECT) strcat(cbuf, "\\");
- if (full) {
- /* Long form, give other info too */
- sprintf(line_buf,"%-13s",cbuf);
- if(sbuf->attr & ST_DIRECT)
- strcat(line_buf," ");/* 11 spaces */
- else {
- sprintf(cbuf,"%ld",sbuf->fsize);
- commas(cbuf);
- sprintf(line_buf+strlen(line_buf),"%10s ",cbuf);
- }
- sprintf(line_buf+strlen(line_buf),"%2d:%02d %2d/%02d/%02d%s",
- (sbuf->ftime >> 11) & 0x1f, /* hour */
- (sbuf->ftime >> 5) & 0x3f, /* minute */
- (sbuf->fdate >> 5) & 0xf, /* month */
- (sbuf->fdate ) & 0x1f, /* day */
- (sbuf->fdate >> 9) + 80, /* year */
- (n & 1) ? " " : "\n");
- fputs(line_buf,file);
- } else {
- fputs(cbuf,file);
- fputs("\n",file);
- }
- }
- /* Provide additional information only on DIR */
- void
- print_free_space(file, n)
- FILE *file;
- int n;
- {
- unsigned long free_bytes, total_bytes;
- char s_free[11], s_total[11];
- char cbuf[20];
- struct regs regs;
-
- if(n & 1)
- fputs("\r\n",file);
-
- /* Find disk free space */
- _AH = GET_FREE;
- _DX = 0; /* Default drive */
- if(sysint(0x21,®s,®s) & FLAG_CARRY)
- ;
-
- free_bytes = (unsigned long)_AX * (unsigned long)_CX;
- total_bytes = free_bytes * (unsigned long)_DX;
- free_bytes *= (unsigned long)_BX;
-
- sprintf(s_free,"%ld",free_bytes); commas(s_free);
- sprintf(s_total,"%ld",total_bytes); commas(s_total);
-
- if(n)
- sprintf(cbuf,"%d",n);
- else
- strcpy(cbuf,"No");
-
- fprintf(file,"%s file%s. %s bytes free. Disk size %s bytes.\n",
- cbuf,(n==1? "":"s"),s_free,s_total);
- }
- void
- free_clist(this)
- struct dirsort *this;
- {
- struct dirsort *next;
-
- while (this != NULLSORT) {
- next = this->next;
- free(this);
- this = next;
- }
- }
- getdir_nosort(path,full,file)
- char *path;
- int full;
- FILE *file;
- {
- struct dirent sbuf;
- int command;
- int n = 0; /* Number of directory entries */
- void format_fname_full(), print_free_space();
-
- path = wildcardize(path);
- command = FIND_FIRST;
- while(nextname(command, path, &sbuf)){
- command = FIND_NEXT; /* Got first one already... */
- if (sbuf.fname[0] == '.') /* drop "." and ".." */
- continue;
- format_fname_full(file, &sbuf, full, ++n);
- }
- if(full)
- print_free_space(file, n);
- return 0;
- }
-
-
-